
package examples.HigherOrder
        -- inline(numfunc)
    where

-- import Data.List 

both :: (forall arg res.arg -> res) -> pb -> cu -> (au, ag)
both f xs ys = (f xs, f ys)

try1 = both (head [])
try2 = both noterm

-- the only way to write a function of type a -> b?
noterm a  = noterm a     


with :: (Num a, Num b) => (forall e.Num e => [e]->[e]) -> [a] -> [b] -> ([a], [b])
with f xs ys = (f xs, f ys)

-- numfunc :: Num a => [a] -> [a]
numfunc = map (fromInt 1+)

-- wrong :: (Enum a, Num a) => ([a], [Integer])
wrong = with nu  (nu  [1..10]) ([100_000_000_000n..100_000_000_010n])
    where
        nu :: Num n => [n] -> [n]
        nu = map (1+)
        
higher :: Num b => (forall a.Num a => f a -> f a) -> f b -> f b
higher f xs = f xs    

-- useh :: (Functor α, Num β) => α β -> α β
useh = higher (fmap (+1)) 

main args
    | null args = print "no args: " 
                    >> println (issue50  [7,6 .. 1]) 
                    >> println (issue50a [7,6 .. 2])
    | otherwise = print "some args: " >> println (useh [1], useh (Just 3.7))     

-- issue 50 (solved): this did not typecheck 
issue50 :: Ord o => [o] -> o
issue50 xs = (ST.run go) 
    where go = return $ minimum xs 

--- without type signature it should compile as well, as it used to be
issue50a xs = (ST.run go) 
    where go = return $ minimum xs 
    